package com.szalay.desktopsearch.ui;

import java.awt.Color;
import java.awt.Component;
import java.awt.Container;
import java.awt.Font;
import java.awt.Frame;
import java.util.Enumeration;
import javax.swing.JDialog;
import javax.swing.Spring;
import javax.swing.SpringLayout;
import javax.swing.UIManager;
import javax.swing.UIManager.LookAndFeelInfo;

/**
 * Configure the Swing UI.
 *
 * @author szalay
 */
public final class UI {

    /**
     *  No instantiation needed.
     */
    private UI() {
        //nothing
    }

    /**
     * Aligns the first
     * <code>rows</code>
     * <code>cols</code> components of
     * <code>parent</code> in a grid. Each component is as big as the maximum preferred width and height of the
     * components. The parent is made just big enough to fit them all.
     *
     * @param rows number of rows
     * @param cols number of columns
     * @param initialX x location to start the grid at
     * @param initialY y location to start the grid at
     * @param xPad x padding between cells
     * @param yPad y padding between cells
     */
    static void makeGrid(Container parent,
            int rows, int cols,
            int initialX, int initialY,
            int xPad, int yPad) {
        SpringLayout layout = (SpringLayout) parent.getLayout();
        Spring xPadSpring = Spring.constant(xPad);
        Spring yPadSpring = Spring.constant(yPad);
        Spring initialXSpring = Spring.constant(initialX);
        Spring initialYSpring = Spring.constant(initialY);
        int max = rows * cols;

        //Calculate Springs that are the max of the width/height so that all
        //cells have the same size.
        Spring maxWidthSpring = layout.getConstraints(parent.getComponent(0)).
                getWidth();
        Spring maxHeightSpring = layout.getConstraints(parent.getComponent(0)).
                getHeight();
        for (int i = 1; i < max; i++) {
            SpringLayout.Constraints cons = layout.getConstraints(
                    parent.getComponent(i));

            maxWidthSpring = Spring.max(maxWidthSpring, cons.getWidth());
            maxHeightSpring = Spring.max(maxHeightSpring, cons.getHeight());
        }

        //Apply the new width/height Spring. This forces all the
        //components to have the same size.
        for (int i = 0; i < max; i++) {
            SpringLayout.Constraints cons = layout.getConstraints(
                    parent.getComponent(i));

            cons.setWidth(maxWidthSpring);
            cons.setHeight(maxHeightSpring);
        }

        //Then adjust the x/y constraints of all the cells so that they
        //are aligned in a grid.
        SpringLayout.Constraints lastCons = null;
        SpringLayout.Constraints lastRowCons = null;
        for (int i = 0; i < max; i++) {
            SpringLayout.Constraints cons = layout.getConstraints(
                    parent.getComponent(i));
            if (i % cols == 0) { //start of new row
                lastRowCons = lastCons;
                cons.setX(initialXSpring);
            } else { //x position depends on previous component
                cons.setX(Spring.sum(lastCons.getConstraint(SpringLayout.EAST),
                        xPadSpring));
            }

            if (i / cols == 0) { //first row
                cons.setY(initialYSpring);
            } else { //y position depends on previous row
                cons.setY(Spring.sum(lastRowCons.getConstraint(SpringLayout.SOUTH),
                        yPadSpring));
            }
            lastCons = cons;
        }

        //Set the parent's size.
        SpringLayout.Constraints pCons = layout.getConstraints(parent);
        pCons.setConstraint(SpringLayout.SOUTH,
                Spring.sum(
                Spring.constant(yPad),
                lastCons.getConstraint(SpringLayout.SOUTH)));
        pCons.setConstraint(SpringLayout.EAST,
                Spring.sum(
                Spring.constant(xPad),
                lastCons.getConstraint(SpringLayout.EAST)));
    }

    /* Used by makeCompactGrid. */
    private static SpringLayout.Constraints getConstraintsForCell(
            int row, int col,
            Container parent,
            int cols) {
        SpringLayout layout = (SpringLayout) parent.getLayout();
        Component c = parent.getComponent(row * cols + col);
        return layout.getConstraints(c);
    }

    /**
     * Aligns the first
     * <code>rows</code>
     * <code>cols</code> components of
     * <code>parent</code> in a grid. Each component in a column is as wide as the maximum preferred width of the
     * components in that column; height is similarly determined for each row. The parent is made just big enough to fit
     * them all.
     *
     * @param rows number of rows
     * @param cols number of columns
     * @param initialX x location to start the grid at
     * @param initialY y location to start the grid at
     * @param xPad x padding between cells
     * @param yPad y padding between cells
     */
    static void makeCompactGrid(Container parent, int rows, int cols, int initialX, int initialY,
            int xPad, int yPad) {
        final SpringLayout layout = (SpringLayout) parent.getLayout();
        
        //Align all cells in each column and make them the same width.
        Spring x = Spring.constant(initialX);
        for (int c = 0; c < cols; c++) {
            Spring width = Spring.constant(0);
            for (int r = 0; r < rows; r++) {
                width = Spring.max(width,
                        getConstraintsForCell(r, c, parent, cols).
                        getWidth());
            }
            for (int r = 0; r < rows; r++) {
                SpringLayout.Constraints constraints =
                        getConstraintsForCell(r, c, parent, cols);
                constraints.setX(x);
                constraints.setWidth(width);
            }
            x = Spring.sum(x, Spring.sum(width, Spring.constant(xPad)));
        }

        //Align all cells in each row and make them the same height.
        Spring y = Spring.constant(initialY);
        for (int r = 0; r < rows; r++) {
            Spring height = Spring.constant(0);
            for (int c = 0; c < cols; c++) {
                height = Spring.max(height,
                        getConstraintsForCell(r, c, parent, cols).
                        getHeight());
            }
            for (int c = 0; c < cols; c++) {
                SpringLayout.Constraints constraints =
                        getConstraintsForCell(r, c, parent, cols);
                constraints.setY(y);
                constraints.setHeight(height);
            }
            y = Spring.sum(y, Spring.sum(height, Spring.constant(yPad)));
        }

        //Set the parent's size.
        SpringLayout.Constraints pCons = layout.getConstraints(parent);
        pCons.setConstraint(SpringLayout.SOUTH, y);
        pCons.setConstraint(SpringLayout.EAST, x);
    }
    
    /**
     * Configure the swing layout.
     */
    public static void configure() throws Exception {
        for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
            if ("Nimbus".equals(info.getName())) {
                UIManager.setLookAndFeel(info.getClassName());
                break;
            }
        }

        final Font ourFont = new Font("Sans Serif", Font.PLAIN, 11);
        final Color backgroundColor = Color.white;

        Enumeration e = UIManager.getDefaults().keys();
        while (e.hasMoreElements()) {
            Object elementKey = e.nextElement();
            if (elementKey.toString().endsWith(".font")) {
                UIManager.put(elementKey, ourFont);
            }

            if (elementKey.toString().endsWith("background")) {
                UIManager.put(elementKey, backgroundColor);
            }

            if (elementKey.toString().endsWith(".selectionBackground")) {
                UIManager.put(elementKey, Color.black);
            }

            if (elementKey.toString().endsWith(".selectionForeground")) {
                UIManager.put(elementKey, Color.white);
            }
        }

        UIManager.put("ScrollBar.shadow", Color.black);
        UIManager.put("ScrollBar.thumbLightShadow", Color.black);
        UIManager.put("ScrollBar.highlight", Color.black);
        UIManager.put("ScrollBar.thumb", Color.black);
        UIManager.put("ScrollBar.track", Color.black);
    }
    
     /**
     *  Center a frame within the screen.
     * @param frame
     */
    static void centerScreen(final Frame frame) {
        frame.setLocationRelativeTo(null);
        frame.requestFocus();
    }

    /**
     *  Center a dialog within the screen.
     * @param frame
     */
    static void centerScreen(final JDialog frame) {
        frame.setLocationRelativeTo(null);
        frame.requestFocus();
    }
}
